package com.huwei.servie;

import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.huwei.constant.EhcacheConstant;
import com.huwei.constant.JsonResult;
import com.huwei.constant.ResultErrorConstant;
import com.huwei.data.CacheDataSource;
import com.huwei.data.manager.DataSourceManager;
import com.huwei.data.manager.DataSourceManagerFacotry;
import com.huwei.util.AliyunSmsUtil;
import com.huwei.util.BeanUtil;
import com.huwei.util.CheckCodeUtil;
import com.huwei.util.RedisKeyUtil;
import com.huwei.util.RedisUtil;
import com.huwei.util.SmsCode;
import com.huwei.vo.SmsCodeRequestConstraint;
import com.huwei.vo.TargetCacheInfo;

@Service
public class CodeService {
	
	@Autowired
	private DataSourceManagerFacotry dataSourceManagerFacotry;
	@Autowired
	private RedisUtil redisUtil;
	@Autowired
	private AliyunSmsUtil aliyunSmsUtil;
	/**
	 * 验证码过期时间
	 *单位：秒
	 */
	final private Integer codeTimeOut = Integer.valueOf(5 * 60); 
	final private TimeUnit unit = TimeUnit.SECONDS;
	
	/**
	 * 	获取手机校验码
	 * @return
	 */
	public String requestSmsCode(String phone) {
		String phoneKey = RedisKeyUtil.generateKey(RedisKeyUtil.SMS_KEY_PREFIX, phone);
		DataSourceManager<CacheDataSource> dsm = dataSourceManagerFacotry.getDataManager(CacheDataSource.class);
		CacheDataSource dso = dsm.manager();
		SmsCodeRequestConstraint constraint = (SmsCodeRequestConstraint) dso.find(new TargetCacheInfo(EhcacheConstant.CACHE_NAME_SMS_CODE, phoneKey));
		if(Objects.nonNull(constraint)) {
			//规则1，一天之内错误最高次数不能超过5次
			if(constraint.getCount() > 5) {
				return JsonResult.failed("已达到最高请求次数，请明天再试", ResultErrorConstant.SMS_CODE_ERROR_MAX);
			}
			//规则2，两次请求间隔时间不小于60秒
			if(System.currentTimeMillis() - constraint.getLastTime().getTime() <= 60 * 1000) {
				return JsonResult.failed("请求太快，请稍后再试", ResultErrorConstant.SMS_CODE_REQUEST_QUICK);
			}
		}
		else {
			Date d = new Date();
			constraint = new SmsCodeRequestConstraint(0, d, d, null, phone);
		}
		String smsCode = SmsCode.randomCode();
		constraint.setCount(constraint.getCount() + 1);
		constraint.setLastTime(new Date());
		constraint.setSmsCode(smsCode);
		//到下一天剩余时间
		Long currentTimestamps=System.currentTimeMillis();
		Long nextDayTime = 60*60*24*1000 - (currentTimestamps+60*60*8*1000 ) % 60*60*24*1000;
		dsm.manager().update(new TargetCacheInfo(EhcacheConstant.CACHE_NAME_SMS_CODE, phoneKey), constraint ,nextDayTime ,TimeUnit.MILLISECONDS);
		
		//发送smscode
		aliyunSmsUtil.asynSendSMSCode(phone, smsCode);
		return JsonResult.success(null, BeanUtil.toMap("smsCode" ,smsCode));
	}

	public String imageCheckCode(int width ,int height) {
		try {
			CheckCodeUtil.CheckCodeVo ccv = CheckCodeUtil.imageCode(width, height, 4);
			String key = CheckCodeUtil.generateCheckCodeKey();
			//缓存
			redisUtil.opsForString().set(key, BeanUtil.toJson(ccv) ,codeTimeOut ,unit);
			Map<String, Object> map = new HashMap<String, Object>();
			map.put("checkCode",ccv.getBase64());
			map.put("checkCodeKey", key);
			return JsonResult.success("success", map);
		} catch (IOException e) {
		}
		return JsonResult.failed("generate checked code failed ",ResultErrorConstant.CHECK_CODE_GENERATE_FAILED);
	}
}
